package lol.clann.bukkit.pluginboot.version.v1_7;

import lol.clann.bukkit.pluginboot.version.VersionSetup;
import lol.clann.clannboot.util.clazz.MapperManager;
import org.apache.commons.lang3.tuple.MutablePair;
import org.bukkit.Bukkit;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author pyz
 * @date 2018/10/5 下午8:49
 */
public class MappingSetup_v1_7 {

    private static final Map<String, String> mapping = new HashMap<>();

    public static void setup() {
        try {

            List<String> fieldMapping = getLines("mapping/v1_7/fields.csv");
            parse(fieldMapping);
            List<String> methodMapping = getLines("mapping/v1_7/methods.csv");
            parse(methodMapping);

            List<String> compile2dev = getLines("mapping/v1_7/cb2pkgmcp.srg");
            List<String> compile2runtime = getLines("mapping/v1_7/cb2numpkg.srg");

            // 先把dev compile runtime一一对应起来
            Map<String, MutablePair<String, String>> all = new LinkedHashMap<>();
            String[] ss;
            for (String s : compile2dev) {
                if ((ss = split(s)) == null) {
                    continue;
                }
                if (s.startsWith("MD:")) {
                    all.put(ss[1] + " " + ss[2], MutablePair.of(s, null));
                } else {
                    all.put(ss[1], MutablePair.of(s, null));
                }
            }

            for (String s : compile2runtime) {
                if ((ss = split(s)) == null) {
                    continue;
                }
                if (s.startsWith("MD:")) {
                    all.get(ss[1] + " " + ss[2]).setRight(s);
                } else {
                    all.get(ss[1]).setRight(s);
                }
            }

            // 开始解析
            for (MutablePair<String, String> entry : all.values()) {
                String[] compile2devLine = entry.getLeft().split(" ");
                // 只处理nms
                if (!compile2devLine[1].startsWith("net.minecraft")) {
                    continue;
                }
                String[] compile2runtimeLine = entry.getRight().split(" ");
                switch (compile2devLine[0]) {
                    case "CL:":
                        parseClass(compile2devLine, compile2runtimeLine);
                        break;
                }
            }

            // 设置转换器
            MapperManager.setClassMapper(dev -> {
                dev = dev.replace("{nms}", VersionSetup.getNMSPrefix())
                        .replace("{cb}", VersionSetup.getCBPrefix());
                return mapping.getOrDefault(dev, dev);
            });
            MapperManager.setFieldMapper((clazz, runtimeField) -> mapping.getOrDefault(runtimeField, runtimeField));
            MapperManager.setMethodMapper((clazz, runtimeMethod, paramTypes) -> mapping.getOrDefault(runtimeMethod, runtimeMethod));
        } catch (Throwable e) {
            // 到这里还没初始化第三方库,所以不能用LazyLogger
            e.printStackTrace();
            Bukkit.shutdown();
        }
    }

    private static void parse(List<String> fieldMapping) {
        for (String s : fieldMapping) {
            if (s == null) {
                continue;
            }
            String[] ss = s.split(",");
            if (ss.length < 2) {
                continue;
            }
            mapping.put(ss[0], ss[1]);
        }
    }

    private static void parseClass(String[] compile2devLine, String[] compile2runtimeLine) {
        String compile = compile2devLine[1];
        compile = VersionSetup.getNMSPrefix() + "." + compile.substring(compile.lastIndexOf(".") + 1);
        String runtime = compile2runtimeLine[2].intern();
        mapping.put(compile, runtime);
    }


    private static String[] split(String line) {
        if (line == null || line.length() <= 4) {
            return null;
        }
        String[] ss = line.split(" ");
        if (ss.length < 3) {
            return null;
        }
        return ss;
    }

    private static List<String> getLines(String path) throws IOException {
        List<String> list = new ArrayList<>();
        try (InputStream in = MappingSetup_v1_7.class.getClassLoader().getResourceAsStream(path)) {
            if (in == null) {
                throw new RuntimeException("在classpath中没有找到: " + path);
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) {
                list.add(line.replace("/", "."));
            }
        }
        return list;
    }
}
